<?php

namespace App\Services;

use App\Logging\Service\LogService;

class ExceptionService
{
    // 异常通知状态
    const EXCEPTION_NOTIFY_STATUS_ENABLE = 1; // 开启
    const EXCEPTION_NOTIFY_STATUS_DISABLE = 0; // 关闭

    /**
     * @var array 异常回调列表
     */
    protected $exceptionCallbackList = [];

    /**
     * @var array 不通知的异常
     */
    protected $dontNotify = [
        //
    ];

    /**
     * @var bool 异常通知状态
     */
    protected $exceptionNotifyStatus = self::EXCEPTION_NOTIFY_STATUS_ENABLE;

    /**
     * @var static 单例模式
     */
    protected static $instance;

    /**
     * 单例模式
     */
    public static function getInstance()
    {
        if (static::$instance instanceof static) {
            return static::$instance;
        }
        static::$instance = new static();
        return static::$instance;
    }

    /**
     * 获取通用异常信息
     * @param \Throwable $e
     *
     * @return string
     * @author Chris Yu <chrisyu@crabapple.top> 2023/12/14
     */
    public static function getCommonMsg(\Throwable $e)
    {
        return $e->getMessage(). "[" . $e->getFile() . '::' . $e->getLine() . "]";
    }

    /**
     * 获取通用异常信息
     * @param \Throwable $e
     *
     * @return array
     * @author Chris Yu <chrisyu@crabapple.top> 2023/12/14
     */
    public static function getCommonMsgArray(\Throwable $e)
    {
        return [
            'file' => $e->getFile(),
            'line' => $e->getLine(),
            'message' => $e->getMessage(),
        ];
    }

    /**
     * 获取调试异常信息
     * @param \Throwable $e
     * @param bool $isString
     *
     * @return array|string
     */
    public static function getDebugMsg(\Throwable $e, $isString = true)
    {
        $data = [
            'name'    => get_class($e),
            'file'    => $e->getFile(),
            'line'    => $e->getLine(),
            'message' => $e->getMessage(),
            'trace'   => $e->getTrace(),
        ];
        if ($isString) {
            return json_encode($data, JSON_UNESCAPED_UNICODE);
        }
        return $data;
    }

    /**
     * 注册异常回调
     * 如果某个变量需要在异常回调中使用，需要使用use传递，如果该变量需要最新值，则需要引用传递
     * @author Chris Yu <chrisyu@crabapple.top> 2023/4/7
     */
    public function registerExceptionCallback(callable $callback)
    {
        $this->exceptionCallbackList[] = $callback;
    }

    public function triggerExceptionCallback(\Throwable $e)
    {
        if ($this->exceptionCallbackList) {
            foreach ($this->exceptionCallbackList as $exceptionCallback) {
                $exceptionCallback($e);
            }
        }
    }

    /**
     * 清除异常回调
     * @author Chris Yu <chrisyu@crabapple.top> 2024/11/12
     */
    public function clearExceptionCallback()
    {
        $this->exceptionCallbackList = [];
    }

    /**
     * 关闭异常通知
     * @author Chris Yu <chrisyu@crabapple.top> 2024/11/12
     */
    public function closeExceptionNotify()
    {
        $this->exceptionNotifyStatus = self::EXCEPTION_NOTIFY_STATUS_DISABLE;
    }
}
